package org.ddevil.data.set;

import java.io.Serializable;
import java.util.List;

import org.ddevil.data.Data;

/**
 * This interface defines the behavior of a Data Set.<br>
 * A Data Set is an ordered collection of records.
 * <p>
 * A record is a group of data where each piece of data in the group has a
 * unique Identifier(Id).<br>
 * All records contained in a Data Set must be of the same type, that is, the
 * set of Identifiers that define each record must be consistent throughout the
 * Data Set.
 * </p>
 * <p>
 * There is no specification on how the records are to be stored except that
 * they must be ordered in some fashion so that they can be retrieved by their
 * index in the DataSet.<br>
 * The data in the records does not need to be ordered and is referenced by
 * an identifier, which is a String value.
 * </p>
 * <p>
 * Records are returned as {@link Data} objects, or multiple records
 * can be returned as a new sub Data Set.
 * </p>
 * <p>
 * <strong>NOTE:</strong> Implementing class is responsible for synchronization
 * on modify if the dataset will be shared between threads.
 * </p>
 *
 * @see org.ddevil.data.Data
 * @see org.ddevil.data.util.DataSetUtils
 * @author Eric Lundin
 * @author Rich
 */
public interface DataSet<T extends Data> extends Serializable, Iterable<T> {

	/**
	 * Export a {@link Data} object for the row with the given index.
	 * <p>
	 * Modifications to the returned object should NOT be reflected in this Data
	 * Set.
	 *
	 * @param rowNum -
	 *            The index of the row in our data set.
	 * @return - A Record object that describes the row at the given index.
	 * @throws IndexOutOfBoundsException
	 *             If rowNum > size()
	 */
	public T exportRecord(int rowNum);

	/**
	 * Return a DataSetInterface subset of this data set containing each of the
	 * records specified by the passed in indices.
	 * <p>
	 * Modifications to the returned object should NOT be reflected in this Data
	 * Set.
	 *
	 * @param indices
	 *            The row indices of the records to export.
	 * @return A {@link DataSetInterface} of records corresponding to the given
	 *         indices.
	 * @throws IndexOutOfBoundsException
	 *             If any of the indices > size()
	 */
	public DataSet<T> exportRecords(int... indices);

	/**
	 * Return the data in the given row with the given Id.
	 * <p>
	 * If the Id doesn't exist for this Data Set a null value will be
	 * returned.
	 *
	 * @param rowIndex
	 *            The index of the row.
	 * @param id
	 *            The Id of the actual piece of data in the row.
	 * @return The value at that location.
	 * @throws IndexOutOfBoundsException
	 *             If rowIndex > size()
	 */
	public Object getDataAt(int rowIndex, String id);

	/**
	 * Attempt to import this criteria into our data set.
	 * <p>
	 * Any attributes in the inData object that are not supported by this data
	 * set will be dropped.<br>
	 * Any attributes that this data set supports that are not contained in the
	 * inData object will be filled in with null values.
	 *
	 * @param inData
	 *            A {@link Data} object giving the data to add.
	 */
	public void importRecord(T inData);

	/**
	 * Attempt to import the data into this data set. Each record in the inData
	 * object will be added, in order, to the end of this data set.
	 * <p>
	 * Any attributes in the inData object that are not supported by this data
	 * set will be dropped.<br>
	 * Any attributes that this data set supports that are not contained in the
	 * inData object will be filled in with null values.
	 *
	 * @param data
	 *            The data to add.
	 */
	public void importRecords(DataSet<T> inData);

	/**
	 * Set the value of the data that is in the given row and id'd with the
	 * given Id.
	 *
	 * @param rowIndex
	 *            The row where the data will be set.
	 * @param id
	 *            The Id of the actual piece of data in the row.
	 * @param data
	 *            The new data value.
	 * @throws IndexOutOfBoundsException
	 *             If rowIndex > size()
	 * @throws IllegalArgumentException
	 *             If the id is invalid for this Data Set.
	 */
	public void setDataAt(int rowIndex, String id, Object data);

	/**
	 * Remove the record at the given index from the data set. All records after
	 * this record will have their index shifted down by one.
	 * <p>
	 *
	 * @param index
	 *            The index of the data row.
	 * @throws IndexOutOfBoundsException
	 *             If rowIndex > size()
	 */
	public void removeRecord(int index);

	/**
	 * Clear all data from this dataset. The set of Id's that define this
	 * data set will remain intact.
	 */
	public void clear();

	/**
	 * Get all the column Identifiers for this data set.
	 * <p>
	 * Modifications to the returned object should NOT be reflected in the Data
	 * Set.
	 *
	 * @return The column IDs.
	 *
	 * TODO remove from API
	 */
	@Deprecated
	public List<String> getIdentifiers();

	/**
	 * Get the number of data rows in the data set.
	 *
	 * @return - The size of our data set.
	 */
	public int size();

}
